package JasPerl::JSTL::Fmt::LocalizationContext;

use 5.010;
use strict;
use warnings;

use Module::Load::Conditional qw(can_load);

use JasPerl::JSTL::Core::Config qw(:fmt);
use JasPerl::Util::Locale;

=head1 NAME

JasPerl::JSTL::Fmt::LocalizationContext - Class representing an I18N
localization context

=head1 SYNOPSIS

=head1 DESCRIPTION

An I18N localization context has two components: a resource bundle and
the locale that led to the resource bundle match.

The resource bundle component is used by <fmt:message> for mapping
message keys to localized messages, and the locale component is used
by the <fmt:message>, <fmt:formatNumber>, <fmt:parseNumber>,
<fmt:formatDate>, and <fmt:parseDate> actions as their formatting or
parsing locale, respectively.

=cut

=head1 FUNCTIONS

=over

=item JasPerl::JSTL::Fmt::LocalizationContext->new( $bundle, $locale )

Constructs an I18N localization context from the given resource bundle
and locale.

The specified locale is the application- or browser-based preferred
locale that led to the resource bundle match.

=cut

my $EMPTY_LOCALIZATION_CONTEXT = __PACKAGE__->new();

sub new {
    my ($class, $handle, $locale) = @_;
    $locale = JasPerl::Util::Locale->from($handle->language_tag)
        unless $locale or not defined $handle;
    $handle->fail_with(\&fail_message) if $handle;
    bless [ $handle, $locale ], $class;
}

sub get_bundle {
    my ($class, $pc, $basename) = @_;
    # TODO: locale?
    return JasPerl::JSTL::Core::Config->find($pc, FMT_LOCALIZATION_CONTEXT)
        unless defined $basename;
    return $EMPTY_LOCALIZATION_CONTEXT
        unless length $basename;

    $basename =~ s/\./::/g;
    if (!can_load( modules => { $basename => undef } )) {
        return $EMPTY_LOCALIZATION_CONTEXT;
    }

    my @locales;
    if (my $locale = JasPerl::JSTL::Core::Config->find($pc, FMT_LOCALE)) {
        @locales = ( $locale );
    } else {
        @locales = $pc->get_request()->get_locales()->list();
    }
    # TODO: fallback locale

    if (my $lh = $basename->get_handle(@locales)) {
        return __PACKAGE__->new($lh);
    } else {
        return $EMPTY_LOCALIZATION_CONTEXT;
    }
}

=item $context->get_handle

=cut

sub get_handle {
    return $_[0]->[0];
}

=item $context->get_locale

Gets the locale of this I18N localization context.  Returns undef if
this I18N localization context is empty, or its resource bundle is a
(locale-less) root resource bundle.

=cut

sub get_locale {
    return $_[0]->[1];
}

sub get_message {
    my ($self, $key, $args) = @_;
    return "??????" unless length $key;
    return "???$key???" unless $self->[0];
    return $self->[0]->maketext($key, @{$args});
}

sub fail_message {
    my ($handle, $key) = @_;
    return "???$key???";
}

1;
